package com.freestyle.nettychat.chat.service;

import com.freestyle.nettychat.chat.dto.AttachmentMessage;
import com.freestyle.nettychat.chat.dto.ChatMessage;
import com.freestyle.nettychat.session.service.SessionService;
import com.freestyle.redis.expire.RedisExpirationTemplate;
import org.springframework.boot.autoconfigure.cache.CacheProperties;
import org.springframework.data.redis.core.RedisTemplate;

import java.time.Duration;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Created by rocklee on 2022/2/4 21:53
 */
public class  RedisChatService implements ChatService {
  private static final String KEY_CHAT_QUEUE_PREFIX="NETTY_CHAT_CHAT-";
  private static final String KEY_ACTIVE_CHATROOM_SET="NETTTY_CHAT_ACTIVE_CHATROOM";
  private static final String KEY_ATTACHMENT_MAP="NETTY_CHAT_ATTACH";

  private RedisExpirationTemplate<String,Object> redisTemplate;
  private SessionService sessionService;
  @Override
  public void setSessionService(SessionService sessionService) {
    this.sessionService = sessionService;
  }

  public RedisChatService(RedisExpirationTemplate<String, Object> redisTemplate) {
    this.redisTemplate = redisTemplate;
  }
  private long getCurrentTime(){
    return new Date().getTime();
  }
  public RedisTemplate getRedisTemplate(){
    return redisTemplate.getTemplate();
  }
  @Override
  public void sendMessage(ChatMessage chatMessage) {
     String chatRoom=chatMessage.getProperties().getChatRoom();
     if  (!redisTemplate.getTemplate().opsForSet().isMember(KEY_ACTIVE_CHATROOM_SET,chatRoom)){
       redisTemplate.getTemplate().opsForSet().add(KEY_ACTIVE_CHATROOM_SET,chatRoom);
     }
    if (chatMessage instanceof AttachmentMessage){
      //如果是附件，则将附件内容另存至附件map,有效期1天
     /* String md5=Md5Crypt.md5Crypt (((AttachmentMessage)chatMessage).getData());
      chatMessage.getProperties().setMD5(md5);*/
      redisTemplate.mapAdd(KEY_ATTACHMENT_MAP,chatMessage.getProperties().getMD5(),chatMessage, Duration.ofDays(1));
      chatMessage.setData(null);
    }
    String group=getChatRoomKey(chatRoom);
    redisTemplate.getTemplate().opsForZSet().add(group,chatMessage,getCurrentTime());
  }

  @Override
  public List<ChatMessage> recvChatRoomMessage(String chatRoom, double min, double max, int limit) {
    RedisTemplate<String,Object> template=redisTemplate.getTemplate();
    return template.opsForZSet().rangeByScore(getChatRoomKey(chatRoom),min,max,0,limit)
            .stream().map(o->
            {
              if (o instanceof AttachmentMessage){
                AttachmentMessage message=(AttachmentMessage)o;
                message.setData(null);
              }
              return (ChatMessage)o;
            }).collect(Collectors.toList());
  }

  @Override
  public AttachmentMessage recvAttachment(String attachmentId) {
    AttachmentMessage message= (AttachmentMessage) redisTemplate.getTemplate().opsForHash().get(KEY_ATTACHMENT_MAP,attachmentId);
    if (message==null){
      throw new IllegalStateException("附件无效或已过期");
    }
    return message;
  }

  @Override
  public void clearOldChatLog(int keepDays) {
    Calendar calendar=Calendar.getInstance();
    calendar.add(Calendar.DAY_OF_YEAR,-keepDays);
    long tm=calendar.getTime().getTime();
    sessionService.getOnLineChatRoom().keySet().forEach(k->{
      String group=getChatRoomKey(k);
      Set<Object> logs= redisTemplate.getTemplate().opsForZSet().rangeByScore(group,0,tm);
      logs.stream().forEach(l->{
        if (l instanceof ChatMessage){
          String md5=((ChatMessage) l).getProperties().getMD5();
          if (md5!=null){
             redisTemplate.mapRemove(KEY_ATTACHMENT_MAP,md5);
          }
        }
      });
      redisTemplate.getTemplate().opsForZSet().removeRangeByScore(group,0,tm);
    });

  }
  private String getChatRoomKey(String chatRoom){
    return KEY_CHAT_QUEUE_PREFIX+chatRoom;
  }
  @Override
  public void removeChatRoomLog(String chatRoom) {
    redisTemplate.getTemplate().delete(getChatRoomKey(chatRoom));//删除zset类型的聊天记录
    redisTemplate.getTemplate().opsForSet().remove(KEY_ACTIVE_CHATROOM_SET,1,chatRoom);
  }
}
